#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "parse.h"
// echo abc
void parse_cmd(char *line, struct cmd *cmd)
{
    cmd->argc = 0;
    cmd->input = NULL;
    cmd->output = NULL;
    char *arg;
    arg = strtok(line, " ");
    while (arg != NULL)
    {
        switch (arg[0])
        {
        case '>':
            cmd->output = arg + 1;
            break;
        case '<':
            cmd->input = arg + 1;
            break;
        default:
            cmd->argv[cmd->argc] = arg;
            cmd->argc++;
        }
        arg = strtok(NULL, " ");
    }
    cmd->argv[cmd->argc] = NULL;
}

void dump_cmd(struct cmd *cmd)
{
    printf("argc = %d\n", cmd->argc);
    int i;
    for (i = 0; i < cmd->argc; i++)
    {
        printf("argv[%d] = (%s)\n", i, cmd->argv[i]);
    }
    printf("input = (%s)\n", cmd->input);
    printf("output = (%s)\n", cmd->output);
}

int parse_pipe_cmd(char *line, struct cmd *cmdv)
{
    int cmdc = 0;
    char *save;
    char *cmd = strtok_r(line, "|", &save);
    while (cmd != NULL)
    {
        parse_cmd(cmd, &cmdv[cmdc]);
        cmdc++;
        cmd = strtok_r(NULL, "|", &save);
    }
    return cmdc;
}

void dump_pipe_cmd(int cmdc, struct cmd *cmdv)
{
    int i;
    printf("pipe cmd, cmdc = %d\n", cmdc);
    for (i = 0; i < cmdc; i++)
    {
        struct cmd *cmd = cmdv + i;
        dump_cmd(cmd);
    }
}
void test_parse_cmd_1()
{
    struct cmd cmd;
    char line[] = "echo abc xyz";
    parse_cmd(line, &cmd);

    assert(cmd.argc == 3);
    assert(strcmp(cmd.argv[0], "echo") == 0);
    assert(strcmp(cmd.argv[1], "abc") == 0);
    assert(strcmp(cmd.argv[2], "xyz") == 0);
    assert(cmd.argv[3] == NULL);
    assert(cmd.input == NULL);
    assert(cmd.output == NULL);
}

// echo abc >log
void test_parse_cmd_2()
{
    struct cmd cmd;
    char line[] = "echo abc >log";
    parse_cmd(line, &cmd);

    assert(cmd.argc == 2);
    assert(strcmp(cmd.argv[0], "echo") == 0);
    assert(strcmp(cmd.argv[1], "abc") == 0);
    assert(cmd.argv[2] == NULL);
    assert(cmd.input == NULL);
    assert(strcmp(cmd.output, "log") == 0);
}

// cat /etc/passwd | wc -l
void test_parse_pipe_cmd_1()
{
    struct cmd cmdv[MAX_CMDC];
    char line[] = "cat /etc/passwd | wc -l";
    int cmdc = parse_pipe_cmd(line, cmdv);

    assert(cmdc == 2);
    assert(cmdv[0].argc == 2);
    assert(strcmp(cmdv[0].argv[0], "cat") == 0);
    assert(strcmp(cmdv[0].argv[1], "/etc/passwd") == 0);
    assert(cmdv[0].argv[2] == NULL);
    assert(cmdv[0].input == NULL);
    assert(cmdv[0].output == NULL);

    assert(cmdv[1].argc == 2);
    assert(strcmp(cmdv[1].argv[0], "wc") == 0);
    assert(strcmp(cmdv[1].argv[1], "-l") == 0);
    assert(cmdv[1].argv[2] == NULL);
    assert(cmdv[1].input == NULL);
    assert(cmdv[1].output == NULL);
}

// cat <input | sort | cat >output
void test_parse_pipe_cmd_2()
{
    struct cmd cmdv[MAX_CMDC];
    char line[] = "cat <input | sort | cat >output";
    int cmdc = parse_pipe_cmd(line, cmdv);

    assert(cmdc == 3);
    assert(cmdv[0].argc == 1);
    assert(strcmp(cmdv[0].argv[0], "cat") == 0);
    assert(cmdv[0].argv[1] == NULL);
    assert(strcmp(cmdv[0].input, "input") == 0);
    assert(cmdv[0].output == NULL);

    assert(cmdv[1].argc == 1);
    assert(strcmp(cmdv[1].argv[0], "sort") == 0);
    assert(cmdv[1].argv[1] == NULL);
    assert(cmdv[1].input == NULL);
    assert(cmdv[1].output == NULL);

    assert(cmdv[2].argc == 1);
    assert(strcmp(cmdv[2].argv[0], "cat") == 0);
    assert(cmdv[2].argv[1] == NULL);
    assert(cmdv[2].input == NULL);
    assert(strcmp(cmdv[2].output, "output") == 0);
}
